﻿#include "FITKNastranAdaptorMAT1.h"

namespace Nastran
{
FITKNastranAdaptorMAT1::~FITKNastranAdaptorMAT1()
{
}

/*!
 *  Adapts material properties from a Nastran MAT1 file.
 *  return True if adaptation is successful, false otherwise.
 *
 * Checks for necessary data availability.
 * Extracts material properties from file content.
 * If 'MAT1*' format is detected, parses properties accordingly.
 * Otherwise, uses an alternative parsing method.
 * Obtains or creates a material object.
 * Configures density, elasticity, expansion, and damping behaviors.
 * Updates the material object with extracted properties.
 */
bool FITKNastranAdaptorMAT1::adaptR()
{
    if (nullptr == _caseData || nullptr == getReader() || _fileContentCache.isEmpty())
    {
        return false;
    }

    int fileMID = 0;
    double fileE = 0;
    double fileNU = 0;
    double fileRHO = 0;
    double fileA = 0;
    double fileTREF = 0;
    double fileGE = 0;
    QString line = _fileContentCache.head();

    if (line.startsWith("MAT1*"))
    {
        // TODO format error process, but now we don't have enough infotmation
        if (_fileContentCache.size() < 2)
        {
            getReader()->consoleMessage(3, "wrong MAT format");
            return false;
        }

        fileMID = line.mid(8 + 16 * 0, 16).toInt();
        fileE = String2Value(line.mid(8 + 16 * 1, 16));
        fileNU = String2Value(line.mid(8 + 16 * 3, 16));
        fileRHO = String2Value(_fileContentCache[1].mid(8 + 16 * 0, 16));
        fileA = String2Value(_fileContentCache[1].mid(8 + 16 * 1, 16));
        fileTREF = String2Value(_fileContentCache[1].mid(8 + 16 * 2, 16));
        fileGE = String2Value(_fileContentCache[1].mid(8 + 16 * 3, 16));
    }
    else
    {
        // TODO format error process, but now we don't have enough infotmation

        fileMID = line.mid(8 * 1, 8).toInt();
        fileE = String2Value( line.mid(8 * 2, 8) );
        fileNU = String2Value(line.mid(8 * 4, 8));
        fileRHO = String2Value(line.mid(8 * 5, 8));
        fileA = String2Value(line.mid(8 * 6, 8));
        fileTREF = String2Value(line.mid(8 * 7, 8));
        fileGE = String2Value(line.mid(8 * 8, 8));
    }

    Interface::FITKAbaMaterial *materialPtr = nullptr;

    Interface::FITKMaterialManager *materialManager = _caseData->getMaterialManager();

    if (nullptr == materialManager)
    {
        getReader()->consoleMessage(3, "nullptr error for material manager");
        return false;
    }
    else
    {
        materialPtr = dynamic_cast<Interface::FITKAbaMaterial *>(
            _caseData->getMaterialManager()->getDataByName(QString::number(fileMID)));
    }

    if (nullptr == materialPtr)
    {
        materialPtr = new Interface::FITKAbaMaterial();
        materialPtr->setDataObjectName(QString::number(fileMID));
        _caseData->getMaterialManager()->appendDataObj(materialPtr);
    }
    else
    {
        getReader()->consoleMessage(
            2, QString("The material %1 already exists, now will cover it").arg(materialPtr->getDataObjectName()));
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Density);

    Interface::FITKAbaMaterialDensity *densityBehavior = dynamic_cast<Interface::FITKAbaMaterialDensity *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Density));

    if (nullptr != densityBehavior)
    {
        densityBehavior->setMassDensity(fileRHO);
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Elastic);
    Interface::FITKAbaMaterialElastic *materialBevior = dynamic_cast<Interface::FITKAbaMaterialElastic *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Elastic));

    if (nullptr != materialBevior)
    {
        materialBevior->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::IsoTropic);
        materialBevior->setIsotropicYoungsModulus(fileE);
        materialBevior->setIsotropicPoissonRatio(fileNU);
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Expansion);
    Interface::FITKAbaMaterialExpansion *expensionBehavior = dynamic_cast<Interface::FITKAbaMaterialExpansion *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Expansion));

    if (nullptr != expensionBehavior)
    {
        expensionBehavior->setExpansionType(Interface::FITKAbaMaterialBehaviorEnum::Isotropic);
        expensionBehavior->setIsotropicTemperature(fileTREF);
        expensionBehavior->setIsoTropicExpansionCoeff(fileA);
    }

    materialPtr->addMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Damping);
    Interface::FITKAbaMaterialDamping *dampingBehavior = dynamic_cast<Interface::FITKAbaMaterialDamping *>(
        materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Damping));

    if (nullptr != dampingBehavior)
    {
        dampingBehavior->setStructural(fileGE);
    }

    return true;
}

bool FITKNastranAdaptorMAT1::adaptW()
{
    if (nullptr == _caseData || nullptr == getWriter())
    {
        return false;
    }
    Interface::FITKMaterialManager *materialMgr = _caseData->getMaterialManager();
    if (materialMgr == nullptr) return false;

    const int count = materialMgr->getDataCount();
    for (int index = 0; index < count; index++)
    {
        Interface::FITKAbaMaterial *materialPtr = dynamic_cast<Interface::FITKAbaMaterial *>(materialMgr->getDataByIndex(index));
        if (materialPtr == nullptr) continue;
        Interface::FITKAbaMaterialDensity *densityBehavior = dynamic_cast<Interface::FITKAbaMaterialDensity *>(
            materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Density));
        Interface::FITKAbaMaterialElastic *elasticBevior = dynamic_cast<Interface::FITKAbaMaterialElastic *>(
            materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Elastic));
        Interface::FITKAbaMaterialExpansion *expensionBehavior = dynamic_cast<Interface::FITKAbaMaterialExpansion *>(
            materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Expansion));
        Interface::FITKAbaMaterialDamping *dampingBehavior = dynamic_cast<Interface::FITKAbaMaterialDamping *>(
            materialPtr->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::Damping));
        if (densityBehavior == nullptr || elasticBevior == nullptr || expensionBehavior == nullptr || dampingBehavior == nullptr) continue;

        //Material ID == materialPtr Name
        QString fileMID = materialPtr->getDataObjectName();
        //RHO
        double fileRHO = densityBehavior->getMassDensity();
        //E NU
        double fileE = elasticBevior->getIsotropicYoungsModulus();
        double fileNU = elasticBevior->getIsotropicPoisssonRatio();
        //TREF A
        double fileTREF = expensionBehavior->getIsotropicTemperature();
        double fileA = expensionBehavior->getIsotropicExpansionCoeff();
        //GE
        double fileGE = dampingBehavior->getStructural();
        //G
        double fileG = fileE / (2 * (1 + fileNU));
        //写入队列 顺序为 MID E G NU RHO A TREF GE 其中G=E/2(1+NU)
        _fileContentCache.append("$$");
        _fileContentCache.append("$$  MAT1 Data");
        _fileContentCache.append("$");
        _fileContentCache.append("$HMNAME MAT                    " + fileMID + "\"material" + fileMID + "\" \"MAT" + fileMID + "\"");
        _fileContentCache.append("$HWCOLOR MAT                   " + fileMID + "       0");//TODO:颜色相关 暂时设置为0
        QString tempStr;
        QString fileMIDStr = "MAT" + fileMID;
        tempStr.append(fileMIDStr);
        for (int i = fileMIDStr.size(); i < 8; i++)
            tempStr.append(" ");
        tempStr.append(Interface::FITKAbstractTextWriter::int2String(fileMID.toInt(), 8));
        tempStr.append(Value2StringLeft(fileE));
        tempStr.append(Value2StringLeft(fileG));
        tempStr.append(Value2StringLeft(fileNU));
        tempStr.append(Value2StringLeft(fileRHO));
        tempStr.append(Value2StringLeft(fileA));
        tempStr.append(Value2StringLeft(fileTREF));
        tempStr.append(Value2StringLeft(fileGE));
        _fileContentCache.append(tempStr);
    }
    return true;
}

// Assigns the provided FITKDataCase object to the _caseData member variable.
void FITKNastranAdaptorMAT1::setCaseData(AbaqusData::FITKDataCase *caseData)
{
    _caseData = caseData;
}

// Set the file content cache for the FITKNastranAdaptorMAT1 class
void FITKNastranAdaptorMAT1::setFileContentCache(QQueue<QString> cache)
{
    // Assign the provided cache to the class's file content cache
    _fileContentCache = cache;
}

void FITKNastranAdaptorMAT1::getFileContentCache(QQueue<QString>& cache)
{
    cache = _fileContentCache;
}

QString FITKNastranAdaptorMAT1::Value2StringLeft(double d, int prec, int width1, char f)
{
    QRegExp reg;
    QString strNumber = QString("%1").arg(d, 0, f, prec);
    QString rtStr = strNumber;
    //判断0 
    if (fabs(d) < 1e-16)
    {
        return "";
    }
    else if (f == 'g' && (fabs(d) >= 1e+4 || fabs(d) <= 1e-4))
    {
        strNumber = QString("%1").arg(d, 0, 'e', prec - 1);
    }

    if (strNumber.contains("e"))
    {
        reg.setPattern("0+\\e");
        rtStr = strNumber.replace(reg, "e");
    }
    else if (strNumber.contains("E"))
    {
        reg.setPattern("0+\\E");
        rtStr = strNumber.replace(reg, "e");
    }
    else if (!strNumber.contains("."))
    {
        rtStr = strNumber + ".0";
    }
    else
    {
        reg.setPattern("0+$");
        rtStr = strNumber.replace(reg, "");
    }

    rtStr = rtStr.replace(".e", "e");
    //bdf特殊处理
    if (rtStr.size() > 8 && rtStr.mid(0, 3) == "-0.")
        rtStr = rtStr.replace("-0.", "-.");
    if (rtStr.size() > 8 && rtStr.mid(0, 2) == "0.")
        rtStr = rtStr.replace("0.", ".");
    if (rtStr.size() > 8 && rtStr.contains("e-0"))
        rtStr = rtStr.replace("e-0", "-");
    if (rtStr.contains("e"))
        rtStr = rtStr.replace("e", "");
    rtStr = rtStr.leftJustified(width1, ' ');
    
    return rtStr;
}

} // namespace Nastran